package persi.hibernate;

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

import persi.hibernate.transactionStatus.TransactionBeginStatus;
import persi.hibernate.transactionStatus.TransactionNotCreatedStatus;
import persi.hibernate.transactionStatus.TransactionStatus;

/**
 * 
 * @author leezsi Clase que encapsula el manejo de las sesiones y las
 *         transacciones de Hibernate
 */
public class HibernateUtils {

	private static SessionFactory sessionFactory;
	// Guardo lasesion actual del usuario
	private static ThreadLocal<Session> session = new ThreadLocal<Session>();
	// Guardo la transaccion actual del usuario
	private static ThreadLocal<Transaction> transaction = new ThreadLocal<Transaction>();
	private static ThreadLocal<TransactionStatus> status = new ThreadLocal<TransactionStatus>() {
		@Override
		protected TransactionStatus initialValue() {
			return new TransactionNotCreatedStatus();
		};
	};

	static {
		// Esta instancia es thread safe
		HibernateUtils.sessionFactory = new Configuration().configure()
				.buildSessionFactory();
	}

	/**
	 * Cierra la sesion actual del usuario
	 */
	public static void closeSession() {
		HibernateUtils.getSession().close();
	}

	/**
	 * comitea la transaccion actual
	 */
	public static void commit() {
		HibernateUtils.status.get().commit(HibernateUtils.beginTransaction());
	}

	/**
	 * Crea la sesion
	 * 
	 * @return la nueva sesion
	 */
	public static Session createSession() {
		final Session newSession = HibernateUtils.sessionFactory.openSession();
		HibernateUtils.session.set(newSession);
		return newSession;
	}

	public static ThreadLocal<Transaction> getLocalTransaction() {
		return HibernateUtils.transaction;
	}

	/**
	 * Retorna la sesion actual
	 * 
	 * @return la sesion actual del usuario
	 */
	public static Session getSession() {
		return HibernateUtils.session.get();
	}

	public static SessionFactory getSessionFactory() {
		return HibernateUtils.sessionFactory;
	}

	public static ThreadLocal<TransactionStatus> getStatus() {
		return HibernateUtils.status;
	}

	/**
	 * Devuelve la transaccion del usuario.<br/>
	 * si no existe la crea.-
	 * 
	 * @return la transaccion del usuario
	 */
	public static Transaction beginTransaction() {
		final Transaction tx = HibernateUtils.transaction.get();
		if (tx == null) {
			HibernateUtils.transaction.set(HibernateUtils.getSession()
					.beginTransaction());
			HibernateUtils.status.set(new TransactionBeginStatus());
		}
		return tx;
	}

	/**
	 * rollback de la transaccion actual
	 */
	public static void rollback() {
		HibernateUtils.status.get().rollback(HibernateUtils.beginTransaction());
	}
}
